﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SharedGenomics.Domain
{
    public class IndividualGenotype
    {
        #region Private Members

        private string _id;
        private Sex _sex;
        private IDictionary<string, MarkerGenotype> _samples;

        #endregion

        #region Constructors

        public IndividualGenotype(string id)
            : this(id, Sex.Unknown)
        {
        }

        public IndividualGenotype(string id, Sex sex)
        {
            this.Id = id;
            this.Sex = sex;
            this._samples = new Dictionary<string, MarkerGenotype>(StringComparer.InvariantCultureIgnoreCase);
        }

        #endregion

        #region Public Methods

        public void AddMarkerGenotype(string markerName, MarkerGenotype genotype)
        {
            if (markerName == null)
                throw new ArgumentNullException("markerName");

            if (!Enum.IsDefined(typeof(MarkerGenotype), genotype))
                throw new ArgumentException(String.Format("{0} is not a valid marker genotype", genotype));

            this._samples[markerName] = genotype;
        }

        public bool TryGetMarkerSample(string markerName, out MarkerGenotype sample)
        {
            //Dictionary.TryGetValue throws exception if key is null
            if (markerName == null)
            {
                sample = MarkerGenotype.Missing;
                return false;
            }

            return this._samples.TryGetValue(markerName, out sample);
        }

        #endregion

        #region Properties

        public string Id
        {
            get { return this._id; }
            set
            {
                if (value == null)
                    throw new ArgumentNullException("Id");

                if (String.IsNullOrEmpty(value))
                    throw new ArgumentException("Identifier cannot be empty");

                this._id = value;
            }
        }

        public Sex Sex
        {
            get { return this._sex; }
            set
            {
                if (Enum.IsDefined(typeof(Sex), value))
                {
                    this._sex = value;
                }
                else
                    throw new ArgumentException(String.Format("{0} is not a defined Sex value", value));
            }
        }

        public MarkerGenotype this[string markerName]
        {
            get
            {
                return this._samples.ContainsKey(markerName) ? this._samples[markerName] : MarkerGenotype.Missing;
            }
            set { this.AddMarkerGenotype(markerName, value); }
        }

        public int MarkerCount
        {
            get { return this._samples.Count; }
        }

        #endregion
    }
}
